package zhklappoint.repositoory;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.util.Assert;

public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

	private final EntityManager entityManager;
	private final JpaEntityInformation<T,?> entityInformation;
	private Class<T> entityClass;

	public BaseRepositoryImpl(JpaEntityInformation<T, ?> enInformation, EntityManager em) {
		super(enInformation, em);
        this.entityInformation = enInformation;
        this.entityManager = em;
	}

	@Override
	public HashMap<String, Object> sqlQuery(String queryString, String countSql, Map<String, ?> values, int firstResult,
			int maxResults, String countName, String rowsName) {
		return sqlQuery(queryString, countSql, values, firstResult, maxResults, countName, rowsName, this.entityClass);
	}
	
	@Override
	public HashMap<String, Object> sqlQuery(String queryString, String countSql, Map<String, ?> values, int firstResult,
			int maxResults, String countName, String rowsName, Class<?> clazz) {
		
		Assert.hasText(queryString, "queryString不能为空");
		
		HashMap<String, Object> map = new HashMap<String, Object>();
		
		Query query = entityManager.createNativeQuery(queryString, clazz);
		Query countQuery = entityManager.createNativeQuery(countSql);
		
		// 给条件赋上值
		if (values != null && !values.isEmpty()) {
			for (Map.Entry<String, ?> entry : values.entrySet()) {
				query.setParameter(entry.getKey(), entry.getValue());
				countQuery.setParameter(entry.getKey(), entry.getValue());
			}
		}
		
		if (firstResult >= 0 && maxResults >= 0) {
			query.setFirstResult(firstResult*maxResults);
			query.setMaxResults(maxResults);
		}
		
		Object results = query.getResultList();
		Object resultsCount = countQuery.getSingleResult();
		
		map.put(countName, resultsCount);
		map.put(rowsName, results);
		return map;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public Page<T> sqlQuery(String queryString, String countSql, Map<String, ?> values, Pageable pageable) {

		Assert.hasText(queryString, "queryString不能为空");

		Query query = entityManager.createNativeQuery(queryString, this.entityClass);
		Query countQuery = entityManager.createNativeQuery(countSql);

		//给条件赋值
		if (values != null && !values.isEmpty()) {
			for (Map.Entry<String, ?> entry : values.entrySet()) {
				query.setParameter(entry.getKey(), entry.getValue());
				countQuery.setParameter(entry.getKey(), entry.getValue());
			}
		}

		if (pageable.getPageNumber() >= 0 && pageable.getPageSize() >= 0) {
			query.setFirstResult(pageable.getPageNumber()*pageable.getPageSize());
			query.setMaxResults(pageable.getPageSize());
		}

		return new PageImpl<T>(query.getResultList(), pageable, Long.parseLong(countQuery.getSingleResult().toString()));
	}

	@Override
	public Page<T> queryByExampleWithRange(Example<T> example, List<Range<T>> ranges, Pageable pageable) {
		Specification<T> byExample = new ExampleSpecification<>(example);
        Specification<T> byRanges = new RangeSpecification<>(ranges);
        return findAll(Specification.where(byExample).and(byRanges), pageable);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Page<T> sqlQuery(String queryString, String countSql, Map<String, ?> values, Pageable pageable,
			Class<?> clazz) {
		
		Assert.hasText(queryString, "queryString不能为空");
		
		Query query = entityManager.createNativeQuery(queryString, clazz);
		Query countQuery = entityManager.createNativeQuery(countSql);
		
		// 给条件赋上值
		if (values != null && !values.isEmpty()) {
			for (Map.Entry<String, ?> entry : values.entrySet()) {
				query.setParameter(entry.getKey(), entry.getValue());
				countQuery.setParameter(entry.getKey(), entry.getValue());
			}
		}
		if (pageable.getPageNumber() >= 0 && pageable.getPageSize() >= 0) {
			query.setFirstResult(pageable.getPageNumber()*pageable.getPageSize());
			query.setMaxResults(pageable.getPageSize());
		}
		return new PageImpl<T>(query.getResultList(), pageable, Long.parseLong(countQuery.getSingleResult().toString()));
	}

	@Override
	public void sqlQuery(String queryString) {
		Assert.hasText(queryString, "queryString不能为空");
		
		Query query = entityManager.createNativeQuery(queryString);
		query.executeUpdate();
		
	}


}
